dojo.require('dojox.timing._base');

var pulsarMonitor = function() {

	// Make a source resolver object.
	var pulsarResolver = atnfPulsarResolver({
      resolverServer: 'localhost:8080'
	});

	var ourSources = [];

	var globalTime = atnfTime().setLocation('parkes');
	
	var statusMessage = null;

	var horizonElevation = atnfAngle(30);
	
	var findSource = function(sourceName) {
		// Check all the sources we have for a particular source name.
		for (var i = 0; i < ourSources.length; i++) {
			if (ourSources[i].details().name === sourceName) {
				return ourSources[i];
			}
		}
		
		return null;
	};

	var tableSafeId = function(source, cellType) {
		var tableId = cellType + '_' + source;
		return tableId.replace(/[\-\+\s]+/g, '_');
	};
	
	var addSource = function(aSource) {
		// Stop the status message display.
		statusMessage.stop();

		if (atnfLibrary.isSource(aSource) === false) {
			// This isn't a valid source, so we exit.
			var sourceEntry = dojo.attr(evtObj.target.id, 'value');
			dojo.attr('sourceNameStatus', 'innerHTML',
				'Unable to resolve ' + sourceEntry + '.');
			return;
		}
		
		// Check if we already know about these sources.
		if (findSource(aSource.name) !== null) {
			// We don't need to add this.
			return;
		}

		// Get the source details.
		var sd = aSource.details();
		dojo.attr('sourceNameStatus', 'innerHTML',
			'Successfully resolved ' + sd.name + '.');
		// Empty the entry box.
		dojo.attr('sourceNameInput', 'value', '');
		
		// Make a new table row, and attach it to the table.
		var nRow = dojo.create('tr');
		dojo.byId('sourceTable').appendChild(nRow);
		
		var nameCell = dojo.create('td', {
			innerHTML: sd.name
		});
		nRow.appendChild(nameCell);
		
		// Get the coordinates in J2000.
		var jCo = sd.coordinate.toJ2000();
		
		var raCell = dojo.create('td', {
			innerHTML: jCo.rightAscension.toTurns().turns2hexa({ 
				units: 'hours'
			})
		});
		nRow.appendChild(raCell);
		var decCell = dojo.create('td', {
			innerHTML: jCo.declination.toTurns().turns2hexa({
				alwaysSigned: true
			})
		});
		nRow.appendChild(decCell);

		// Put some extra information in the table.
		var haCell = dojo.create('td', {
			id: tableSafeId(sd.name, 'hourAngle')
		});
		nRow.appendChild(haCell);
		var azCell = dojo.create('td', {
			id: tableSafeId(sd.name, 'azimuth')
		});
		nRow.appendChild(azCell);
		var elCell = dojo.create('td', {
			id: tableSafeId(sd.name, 'elevation')
		});
		nRow.appendChild(elCell);
		var risenCell = dojo.create('td', {
			id: tableSafeId(sd.name, 'risen')
		});
		nRow.appendChild(risenCell);
		var timeSetRiseCell = dojo.create('td', {
			id: tableSafeId(sd.name, 'timeSetRise')
		});
		nRow.appendChild(timeSetRiseCell);

    // Make another row with some more details.
    nRow = dojo.create('tr', {
      'class': 'detailsRow collapse'
    });
		dojo.byId('sourceTable').appendChild(nRow);
    
    var detailsCell = dojo.create('td', {
      innerHTML: JSON.stringify(aSource.getParameters()),
      colspan: 8
    });
    nRow.appendChild(detailsCell);
		
		// Tell it to use our own global time object.
		aSource.useTime(globalTime);
		
		ourSources.push(aSource);
	};

	var tableUpdates = function() {
		// This routine gets called periodically to update the table.

		// Update our global time to be now.
		globalTime.now();
		
		for (var i = 0; i < ourSources.length; i++) {
			var osDet = ourSources[i].details();

			// Update the hour angle.
			var haId = tableSafeId(osDet.name, 'hourAngle');
			var haString = ourSources[i].hourAngle().toTurns().turns2hexa({
				units: 'hours',
				precision: 0,
				alwaysSigned: true
			});
			dojo.attr(haId, 'innerHTML', haString);
			// Update the azimuth and elevation.
			var currAzEl = ourSources[i].getAzEl();
			var azId = tableSafeId(osDet.name, 'azimuth');
			var azString = dojo.number.round(currAzEl.azimuth.toDegrees(), 3).
				zeroPad(100).leadingPlus().zeroTrail(8);
			dojo.attr(azId, 'innerHTML', azString);
			var elId = tableSafeId(osDet.name, 'elevation');
			var elString = dojo.number.round(currAzEl.elevation.toDegrees(), 3).
				zeroPad(10).leadingPlus().zeroTrail(7);
			dojo.attr(elId, 'innerHTML', elString);
			// Update the rise/set state and time.
			var risenId = tableSafeId(osDet.name, 'risen');
			var riseAngle = currAzEl.elevation.subtract(horizonElevation).
				toDegrees();
			if (riseAngle < 0) {
				dojo.attr(risenId, 'innerHTML', 'R');
			} else {
				dojo.attr(risenId, 'innerHTML', 'S');
			}
			var setId = tableSafeId(osDet.name, 'timeSetRise');
			var setHa = ourSources[i].timeUntilElevation(horizonElevation);
			if (setHa.toTurns() > 1) {
				dojo.attr(setId, 'innerHTML', 'never rises');
			} else if (setHa.toTurns() < -1) {
				dojo.attr(setId, 'innerHTML', 'never sets');
			} else {
				var haTime = setHa.toTurns().turns2hexa({
					units: 'hours',
					precision: 0
				});
				dojo.attr(setId, 'innerHTML', haTime);
			}
		}
	};
	
	var lookupSource = function(evtObj) {
		// Get the entry.
		var sourceEntry = dojo.attr(evtObj.target.id, 'value');

		// Put a status entry onto the page to let the user know what's happening.
		statusMessage = atnfUseful.generateStatusMessage(
			'Finding position for ' + sourceEntry, 'sourceNameStatus');
		statusMessage.start();
		
		// Lookup the source.
		pulsarResolver.setSourceName(sourceEntry).resolveName().
			then(addSource);
	};
	
	// Connect the source name input box.
	atnfUseful.onEnter('sourceNameInput', lookupSource);
	
	// Start updating the table every second.
	var tableTimer = new dojox.timing.Timer();
	tableTimer.setInterval(1000);
	tableTimer.onTick = tableUpdates;
	tableTimer.start();
};

dojo.addOnLoad(pulsarMonitor);
